package com.digital.smartgrow.common.util;

import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;

public class LocalDateUtil {

    public static final String YYYY_MM_DD_HH_MM_SS = "yyyy-MM-dd HH:mm:ss";

    public static final String YYYY_Mm_Dd_Hh_Mm_Ss = "yyyy/MM/dd HH:mm:ss";

    public static final String YYYY_Mm_Dd = "yyyy/MM/dd";

    public static final String YYYY_MM_DD_HH = "yyyy-MM-dd HH";

    public static final String YYYY = "yyyy";

    public static final String YYYYMMDD = "yyyyMMdd";

    public static final String YYYYMMDDHHMMSS = "yyyyMMddHHmmss";

    public static final String YYYYMMDDHHMM = "yyyyMMddHHmm";

    public static final String MMDDHHMMSS = "MMddHHmmss";

    public static final String HHMM = "HH:mm";

    public static final String HH = "HH";

    public static final String MM_DD = "MM-dd";

    public static final String YYYY_MM_DD = "yyyy-MM-dd";

    public static final String YYYY_MM = "yyyy-MM";

    public static final String YYYY_MM_DD_HH_MM_SS_SSS = "yyyy-MM-dd HH:mm:ss.SSS";

    public static final String YYYYMMDD_HH_MM_SS = "yyyy/MM/dd HH:mm:ss";

    public static final String HHmMsS = "HHmmss";

    public static final DateTimeFormatter ymdhmsDtf = DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS);

    public static final DateTimeFormatter hmDtf = DateTimeFormatter.ofPattern(HHMM);

    public static final DateTimeFormatter hDtf = DateTimeFormatter.ofPattern(HH);

    public static final DateTimeFormatter ymdhmsDtf2 = DateTimeFormatter.ofPattern(YYYYMMDDHHMMSS);//年月日时分秒

    public static final DateTimeFormatter mdDtf = DateTimeFormatter.ofPattern(MM_DD);

    public static final DateTimeFormatter YYYY_MM_DD_DTF = DateTimeFormatter.ofPattern(YYYY_MM_DD);

    public static final DateTimeFormatter YYYY_MM_DD_HH_DTF = DateTimeFormatter.ofPattern(YYYY_MM_DD_HH);

    public static final DateTimeFormatter YYYY_MM_DTF = DateTimeFormatter.ofPattern(YYYY_MM);

    public static final DateTimeFormatter ymdhmssDtf = DateTimeFormatter.ofPattern(YYYY_MM_DD_HH_MM_SS_SSS);

    public static final DateTimeFormatter ymdhmDtf = DateTimeFormatter.ofPattern(YYYYMMDDHHMM);

    public static final DateTimeFormatter mdhmsDtf = DateTimeFormatter.ofPattern(MMDDHHMMSS);//月日时分秒

    public static final DateTimeFormatter ymdDtf = DateTimeFormatter.ofPattern(YYYYMMDD);//年月日

    public static final DateTimeFormatter YMD_DTF2 = DateTimeFormatter.ofPattern(YYYY_Mm_Dd);//年月日

    public static final DateTimeFormatter hmsdtf = DateTimeFormatter.ofPattern(HHmMsS);//年月日

    /**
     * 为空则获取当日
     * 获取给定日结束时间
     **/
    public static LocalDateTime getLastTimeOfDay(LocalDateTime ldt) {
        if (ldt == null) ldt = LocalDateTime.now();
        return LocalDateTime.of(ldt.toLocalDate(), LocalTime.MAX);
    }

    /**
     * 为空则获取当日
     * 获取给定日起始时间
     **/
    public static LocalDateTime getFirstTimeOfDay(LocalDateTime ldt) {
        if (ldt == null) ldt = LocalDateTime.now();
        return LocalDateTime.of(ldt.toLocalDate(), LocalTime.MIN);
    }

    public static LocalTime getZeroLocalTime() {
        return LocalTime.now().withHour(0).withMinute(0).withSecond(0).withNano(0);
    }

    /**
     * 为空则获取当月
     * 获取给定月最后一天
     **/
    public static LocalDateTime getLastDayOfMonth(LocalDateTime ldt) {
        if (ldt == null) ldt = LocalDateTime.now();
        return LocalDateTime.of(LocalDate.from(ldt.with(TemporalAdjusters.lastDayOfMonth())), LocalTime.MAX);
    }

    /**
     * 获取给定月最后一天
     **/
    public static LocalDate getLastDayOfMonth(LocalDate ld) {
        if (ld == null) ld = LocalDate.now();
        return LocalDate.from(ld.with(TemporalAdjusters.lastDayOfMonth()));
    }

    /**
     * 获取给定月第一天
     **/
    public static LocalDateTime getFirstTimeOfMonth(LocalDateTime ldt) {
        if (ldt == null) ldt = LocalDateTime.now();
        return LocalDateTime.of(LocalDate.from(ldt.with(TemporalAdjusters.firstDayOfMonth())), LocalTime.MIN);
    }

    /**
     * 获取给定月第一天
     **/
    public static LocalDate getFirstDayOfMonth(LocalDate ld) {
        if (ld == null) ld = LocalDate.now();
        return LocalDate.from(ld.with(TemporalAdjusters.firstDayOfMonth()));
    }

    /**
     * 如果为空则是获取当年的第一天
     */
    public static LocalDateTime getFirstLdtOfYear(LocalDateTime ldt) {
        if (ldt == null) ldt = LocalDateTime.now();
        return LocalDateTime.of(LocalDate.from(ldt.with(TemporalAdjusters.firstDayOfYear())), LocalTime.MIN);
    }

    /**
     * 如果为空则是获取当年的第一天
     */
    public static LocalDate getFirstLdOfYear(LocalDate ld) {
        if (ld == null) ld = LocalDate.now();
        return LocalDate.from(LocalDate.from(ld.with(TemporalAdjusters.firstDayOfYear())));
    }

    /**
     * 如果为空则是获取当年的第后一天
     **/
    public static LocalDateTime getLastLdtOfYear(LocalDateTime ldt) {
        if (ldt == null) ldt = LocalDateTime.now();
        return LocalDateTime.of(LocalDate.from(ldt.with(TemporalAdjusters.lastDayOfYear())), LocalTime.MAX);
    }

    /**
     * 如果为空则是获取当年的第后一天
     **/
    public static LocalDate getLastLdOfYear(LocalDate ld) {
        if (ld == null) ld = LocalDate.now();
        return LocalDate.from(LocalDate.from(ld.with(TemporalAdjusters.lastDayOfYear())));
    }

    /**
     * 获取昨日在本月天数占比
     */
    public static double getTodayOfMonthRatio() {
        LocalDate now = LocalDate.now();
        LocalDate with = now.with(TemporalAdjusters.lastDayOfMonth());
        //本月共计多少天
        int maxDay = with.getDayOfMonth();
        //当天是本月的第几天
        int curDay = now.getDayOfMonth();
        return curDay * 1.0 / maxDay;
    }

    /**
     * 获取去年昨日在去年本月天数占比
     */
    public static double getYesterdayOfLastYearMonthRatio() {
        LocalDate now = LocalDate.now().minusYears(1);
        LocalDate with = now.with(TemporalAdjusters.lastDayOfMonth());
        //本月共计多少天
        int maxDay = with.getDayOfMonth();
        //当天是本月的第几天
        int curDay = now.getDayOfMonth();
        return (curDay - 1) * 1.0 / maxDay;
    }

    /**
     * 获取指定月份共计多少天
     */
    public static int getDaysOfMonth(Date date) {
        return date.toInstant().atZone(ZoneId.systemDefault())
                .toLocalDate()
                .with(TemporalAdjusters.lastDayOfMonth())
                .getDayOfMonth();
    }

    public static int getDaysOfMonth(LocalDate localDate) {
        return localDate.with(TemporalAdjusters.lastDayOfMonth())
                .getDayOfMonth();
    }

    /**
     * 获取昨日在本月天数占比
     */
    public static double getYesterdayOfMonthRatio() {
        LocalDate now = LocalDate.now();
        LocalDate with = now.with(TemporalAdjusters.lastDayOfMonth());
        //本月共计多少天
        int maxDay = with.getDayOfMonth();
        //当天是本月的第几天
        int curDay = now.getDayOfMonth();
        return (curDay - 1) * 1.0 / maxDay;
    }

    /**
     * 转换为年月日时分秒字符串
     */
    public static String formatYmdhmsStr(LocalDateTime ldt) {
        return ldt.format(ymdhmsDtf);
    }

    /**
     * 转换为字符串时间
     */
    public static String formatStrTime(LocalDateTime ldt, DateTimeFormatter dtf) {
        return ldt.format(dtf);
    }

    /**
     * 转换为字符串时间
     */
    public static String formatStrTime(LocalTime ldt, DateTimeFormatter dtf) {
        return ldt.format(dtf);
    }

    /**
     * 转换为字符串时间
     */
    public static String formatStrTime(LocalDate ldt, DateTimeFormatter dtf) {
        return ldt.format(dtf);
    }

    /**
     * 获取当天0点
     */
    public static String getTodayZeroTimeStr() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime curDayZero = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth(), 0, 0, 0);//当天0点
        return formatYmdhmsStr(curDayZero);
    }

    /**
     * 获取当天0点
     */
    public static LocalDateTime getTodayZeroTime() {
        LocalDateTime now = LocalDateTime.now();
        LocalDateTime curDayZero = LocalDateTime.of(now.getYear(), now.getMonth(), now.getDayOfMonth(), 0, 0, 0);//当天0点
        return curDayZero;
    }

    /**
     * 把字符串转换为年月日时分秒
     */
    public static LocalDateTime parseLocalDate(String time) {
        return LocalDateTime.parse(time, ymdhmsDtf);
    }

    /**
     * 把字符串转换为年月日时分秒
     */
    public static LocalDateTime parseLocalDateTime(String time, String pattern) {
        return LocalDateTime.parse(time, DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 把字符串转换为年月日时分秒
     */
    public static LocalDate parseLocalDate(String time, String pattern) {
        return LocalDate.parse(time, DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 把字符串转换为年月日时分秒
     */
    public static LocalDateTime parseDateTime(String time, String pattern) {
        return LocalDateTime.parse(time, DateTimeFormatter.ofPattern(pattern));
    }

    /**
     * 把字符串转换为时分
     */
    public static LocalTime parseHourMinuteLocalTime(String time) {
        return LocalTime.parse(time, hmDtf);
    }

    /**
     * 美化时间格式
     *
     * @param time
     * @return
     */
    public static String beautifyTimeStr(String time) {
        LocalDateTime localDate = LocalDateTime.parse(time, ymdhmsDtf2);
        return localDate.format(ymdhmsDtf);
    }

    /**
     * 获取中文的周几
     *
     * @param localDate
     * @return
     */
    public static String parseCnDayOfWeek(LocalDate localDate) {
        String rs = "";
        int dayOfWeek = localDate.getDayOfWeek().getValue();
        return parseCnDayOfWeek(dayOfWeek);
    }

    /**
     * 获取中文的周几
     *
     * @param
     * @return
     */
    public static String parseCnDayOfWeek(Integer dayOfWeek) {
        String rs = "";
        switch (dayOfWeek) {
            case 1:
                rs = "周一";
                break;
            case 2:
                rs = "周二";
                break;
            case 3:
                rs = "周三";
                break;
            case 4:
                rs = "周四";
                break;
            case 5:
                rs = "周五";
                break;
            case 6:
                rs = "周六";
                break;
            case 7:
                rs = "周日";
                break;
            default:
                rs = "";
        }
        return rs;
    }

    public static LocalDateTime toZone(final LocalDateTime time, final ZoneId fromZone, final ZoneId toZone) {
        final ZonedDateTime zonedtime = time.atZone(fromZone);
        final ZonedDateTime converted = zonedtime.withZoneSameInstant(toZone);
        return converted.toLocalDateTime();
    }

    public static LocalDateTime toZone(final LocalDateTime time, final ZoneId toZone) {
        return toZone(time, ZoneId.systemDefault(), toZone);
    }

    public static LocalDateTime toUtc(final LocalDateTime time, final ZoneId fromZone) {
        return toZone(time, fromZone, ZoneOffset.UTC);
    }

    public static void main(String[] args) {

        LocalDateTime now = LocalDateTime.now();
        System.out.println(now);
        System.out.println(now.getYear() + ":" + now.getMonthValue() + ":" + now.getDayOfMonth());
        LocalDateTime of = LocalDateTime.of(now.getYear(), 1, 1, 0, 0, 0);
        System.out.println(of);

        LocalDateTime firstDayOfYear = LocalDateTime.of(LocalDate.from(LocalDateTime.now().with(TemporalAdjusters.firstDayOfYear())), LocalTime.MIN);
        LocalDateTime lastDayOfYear = LocalDateTime.of(LocalDate.from(LocalDateTime.now().with(TemporalAdjusters.lastDayOfYear())), LocalTime.MAX);
        System.out.println(firstDayOfYear);
        System.out.println(lastDayOfYear);
        LocalDateTime lastLdt = now.minusYears(1);
        System.out.println("lastLdt:" + lastLdt);
//        System.out.println(getFirstDayOfYear(lastLdt));
//        System.out.println(getLastDayOfYear(lastLdt));
//        System.out.println(getLastDayOfMonth(lastLdt));
//        System.out.println(getLastTimeOfDay(lastLdt));
//        System.out.println(getLastTimeOfDay(null));
//        System.out.println(getFirstDayOfMonth(lastLdt));
//        System.out.println(getFirstDayOfMonth(null));

        System.out.println(getFirstTimeOfDay(lastLdt));
        System.out.println(getFirstTimeOfDay(null));

        LocalTime test = getZeroLocalTime();
        System.out.println("test:" + test);

    }

}
